package com.blb.goods_service.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blb.goods_service.entity.Spu;
import com.blb.goods_service.entity.Stock;
import com.blb.goods_service.mapper.SkuMapper;
import com.blb.goods_service.mapper.SpuDetailMapper;
import com.blb.goods_service.mapper.SpuMapper;
import com.blb.goods_service.mapper.StockMapper;
import com.blb.goods_service.service.ISpuService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * spu表，该表描述的是一个抽象性的商品，比如 iphone8 服务实现类
 * </p>
 *
 * @author xray
 * @since 2020-09-07
 */
@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements ISpuService {

    @Autowired
    private SpuMapper spuMapper;

    @Autowired
    private SpuDetailMapper spuDetailMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private StockMapper stockMapper;

    @Autowired
    private RedisTemplate<String,Object> template;

    @Transactional
    @Override
    public void saveSpu(Spu spu) {
        spu.setCreateTime(new Date());
        spu.setLastUpdateTime(new Date());
        //先插入tb_spu
        spuMapper.insert(spu);
        spu.getSpuDetails().setSpuId(spu.getId());
        //再插入tb_spuDetail
        spuDetailMapper.insert(spu.getSpuDetails());
        spu.getSkus().forEach(sku -> {
            sku.setCreateTime(LocalDateTime.now());
            sku.setLastUpdateTime(LocalDateTime.now());
            sku.setSpuId(spu.getId());
            //循环插入tb_sku
            skuMapper.insert(sku);
            Stock stock = new Stock();
            stock.setSkuId(sku.getId());
            stock.setStock(sku.getStock());
            //循环插入tb_stock
            stockMapper.insert(stock);
        });
    }

    @Override
    public Spu findById(Long id) {
        ValueOperations<String, Object> ops = template.opsForValue();
        //先查缓存，缓存有，直接返回不执行同步块，提高效率
        Spu spu = (Spu) ops.get("spu-"+id);
        if(spu == null) {
            //上锁，保证查询缓存，查询数据库，保存缓存同步执行
            synchronized (this) {
                //先查询缓存
                spu = (Spu) ops.get("spu-" + id);
                //如果查到直接返回
                if (spu != null) {
                    System.out.println("从缓存查到" + spu);
                    return spu;
                } else {
                    //如果查不到，查询数据库
                    System.out.println("缓存没有，查询数据库");
                    spu = spuMapper.selectById(id);
                    if (spu != null) {
                        //数据库查到，保存缓存中
                        System.out.println("数据库查到" + spu);
                        ops.set("spu-" + id, spu);
                        return spu;
                    }
                }
                System.out.println("数据库没有查到");
                //数据库查不到返回null
                //将空数据保存到Redis中，配置一定超时
                ops.set("spu-"+id,new Spu(),10, TimeUnit.SECONDS);
                return null;
            }
        }
        return spu;
    }
}
